package com.wooboo.server.ext;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class LogContext {

	private static Map<String, Logger> className2Logger = new HashMap<String, Logger>();
	
	private Map<String, Logcat> className2Logcat = new HashMap<String, Logcat>();	
	private Map<String, Object> parameters = new LinkedHashMap<String, Object>();
	private long requestId = Math.round(Math.random() * 1000000000);
	private boolean parametersUpdated = true;
	private String logPrefix = "";
	
	public LogContext() {
		parameters.put("request_id", requestId);
	}
	
	public void setParameter(String key, Object value) {
		parameters.put(key, value);
		parametersUpdated = true;
	}
	
	public String getLogPrefix() {
		if (parametersUpdated) {
			StringBuffer sb = new StringBuffer();
			for (String key : parameters.keySet()) {
				sb.append("[").append(key).append("=").append(parameters.get(key)).append("]");
			}
			logPrefix = sb.toString();
			parametersUpdated = false;
		}
		return logPrefix;
	}
	
	public long getRequestId() {
		return requestId;
	}
	
	public Logcat getLogcat(Class<?> clazz) {
		String className = clazz.getName();
		Logger logger = null;
		synchronized (className2Logger) {
			logger = className2Logger.get(className);
			if (logger == null) {
				logger = Logger.getLogger(clazz);
				className2Logger.put(className, logger);
			}
		}
		Logcat logcat = null;
		synchronized (className2Logcat) {
			logcat = className2Logcat.get(className);
			if (logcat == null) {
				logcat = new Logcat(logger);
				className2Logcat.put(className, logcat);
			}
		}
		return logcat;
	}
	
	public class Logcat {
		private Logcat(Logger logger) {
			this.logger = logger;
		}
		public Logcat derive(Class<?> clazz) {
			return LogContext.this.getLogcat(clazz);
		}
		public void set(String key, Object value) {
			LogContext.this.setParameter(key, value);
		}
		public long getRequestId() {
			return requestId;
		}
		public void trace(String template, Object... params) {
			logger.trace(getLogPrefix()+template, params);
		}
		public void debug(String template, Object... params) {
			logger.debug(getLogPrefix()+template, params);
		}
		public void debug(Throwable e) {
			StringWriter sWriter = new StringWriter();
			PrintWriter pWriter = new PrintWriter(sWriter);
			try {
				e.printStackTrace(pWriter);
				pWriter.close();
				sWriter.close();
			} catch (IOException e1) {
			}
			String eInfo = sWriter.toString();
			eInfo.replace('\r', ' ');
			eInfo.replace('\n', ' ');
			logger.debug(eInfo);
		}
		private Logger logger;
	}
}
